package com.meshnetics.gb.stack.core.event;

import com.meshnetics.gb.event.EventType;

/**
 * Class representing stack event type.
 *
 * @author mmarkov
 */
public final class StackEventType extends EventType {
    /** Type matching all events. */
    public static final StackEventType ANY_TYPE = new StackEventType(255, "any");

    /**
     * Type for LME (Layer Management Entity) events.
     */
    public static final StackEventType LME_TYPE = new StackEventType(1, "lme");

    /** Type for LDE (Layer Data Entity) events. */
    public static final StackEventType LDE_TYPE = new StackEventType(2, "lde");

    /** Type for internal events. */
    public static final StackEventType SYSTEM_TYPE = new StackEventType(4, "system");

    /**
     * Constructs the StackEventType from the given integer type.
     *
     * @param type the integer type
     * @param name the name of the StackEventType
     */
    private StackEventType(int type, String name) {
        super(type, name);
    }

    /**
     * Creates the StackEventType matching both given EventTypes.
     * It any of the types is synchronous, the resulting type will be synchronous.
     *
     * @param et1 1-st StackEventType
     * @param et2 2-nd StackEventType
     * @return the combination of the given EventTypes
     */
    public static StackEventType combine(StackEventType et1, StackEventType et2) {
        return new StackEventType(et1.type | et2.type, "comp");
    }

    /**
     * Returns true if this StackEventType includes the given one and false otherwise.
     *
     * @param et the type to compare
     * @return true if this StackEventType includes the given one and false otherwise
     */
    public boolean matches(EventType et) {
        return (et instanceof StackEventType) && ((type & et.getType()) == et.getType());
    }

    /**
     * Returns true if this StackEventType is a composite type
     * (i.e. combination of 2 or more types or ANY_TYPE) and false otherwise.
     *
     * @return true if this StackEventType is a composite type
     *         (i.e. combination of 2 or more types or ANY_TYPE) and false otherwise.
     */
    public boolean isComposite() {
        return ((type != LME_TYPE.getType()) && (type != LDE_TYPE.getType())
                && (type != SYSTEM_TYPE.getType()));
    }

    /**
     * Compares the given object for the equality with this State.
     *
     * @param obj the Object to compare with
     * @return true if the given Object is a StackEventType with the same type as this one
     *         and false otherwise
     */
    public boolean equals(Object obj) {
        return ((obj instanceof StackEventType) && ((StackEventType) obj).type == type);
    }
}
